package com.tianji.promotion.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.promotion.domain.enums.UserCouponStatus;
import com.tianji.promotion.domain.po.Coupon;
import com.tianji.promotion.domain.po.UserCoupon;
import com.tianji.promotion.domain.vo.CouponVO;
import com.tianji.promotion.mapper.CouponMapper;
import com.tianji.promotion.service.ICouponService;
import com.tianji.promotion.service.IUserCouponService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.tianji.promotion.domain.enums.CouponStatus.ISSUING;
import static com.tianji.promotion.domain.enums.ObtainType.PUBLIC;

/**
 * <p>
 * 优惠券的规则信息 服务实现类
 * </p>
 *
 * @author yangyu
 * @since 2023-08-03
 */
@Service
@RequiredArgsConstructor
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements ICouponService {

    private final IUserCouponService userCouponService;

    /**
     * 查询发放中的优惠券列表
     * @return 用户端优惠券信息
     */
    @Override
    public List<CouponVO> queryIssuingCoupons() {
        //1.查询发放中的优惠券列表
        //条件：发放中，手动领取
        //coupons：正在发放中的优惠券的数据
        List<Coupon> coupons = list(Wrappers.<Coupon>lambdaQuery()
                //发放中
                .eq(Coupon::getStatus, ISSUING)
                //手动领取
                .eq(Coupon::getObtainWay, PUBLIC));

        if (CollUtils.isEmpty(coupons)) {
            //没有正在发放的优惠券，直接返回空集合
            return CollUtils.emptyList();
        }

        //2.统计当前用户已经领取的优惠券的信息
        //收集所有发放中的优惠券id
        List<Long> couponIds = coupons.stream().map(Coupon::getId).collect(Collectors.toList());

        //2.1.查询当前用户已经领取的优惠券的数据
        List<UserCoupon> userCouponList = userCouponService.list(Wrappers.<UserCoupon>lambdaQuery()
                .eq(UserCoupon::getUserId, UserContext.getUser())
                .in(UserCoupon::getCouponId, couponIds));

        //2.2.统计当前用户对这个优惠券，已经领取的数量
        Map<Long, Long> issuedMap = userCouponList.stream()
                //先对优惠券id分组，然后对分组好的优惠券数据，进行count统计
                .collect(Collectors.groupingBy(UserCoupon::getCouponId, Collectors.counting()));

        //2.3.统计当前用户对优惠券的已经领取并且未使用的数量
        Map<Long, Long> unusedMap = userCouponList.stream()
                .filter(uc -> uc.getStatus() == UserCouponStatus.UNUSED) //未使用
                //对已领取的优惠券进行分组，并且count统计
                .collect(Collectors.groupingBy(UserCoupon::getCouponId, Collectors.counting()));

        //3.封装VO结果
        ArrayList<CouponVO> list = new ArrayList<>(coupons.size());

        //遍历发放中的优惠券列表
        for (Coupon coupon : coupons) {
            //3.1.拷贝po属性到vo
            CouponVO couponVO = BeanUtils.copyBean(coupon, CouponVO.class);
            list.add(couponVO);

            //3.2.是否可以领取：已经被领取的数量 < 优惠券总数量 && 当前用户已经领取的数量 < 每人限领取数量
            couponVO.setAvailable(
                    coupon.getIssueNum() < coupon.getTotalNum()
                    //issuedMap:已领取数量       getUserLimit：每个人限领取的数量
                    && issuedMap.getOrDefault(coupon.getId(),0L) < coupon.getUserLimit()
            );

            //3.3.是否可以使用：当前用户已经领取并且未使用的优惠券数量 > 0
            couponVO.setReceived(unusedMap.getOrDefault(coupon.getId(),0L) > 0);
        }

        return list;
    }
}
